/*

<This Java Class is part of the jMusic API version 1.5, March 2004.>

Copyright (C) 2000 Andrew Sorensen & Andrew Brown

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or any
later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

package jm.audio.synth;

import jm.audio.AOException;
import jm.audio.AudioObject;
import jm.audio.Instrument;

/**
 * @author Andrew Brown
 * @version 1.0, 10 October 2001
 */
public class Spring extends AudioObject {
    //----------------------------------------------
    // Attributes
    //----------------------------------------------
    private SpringPipe springNetwork;
    private int numberOfNodes = 8;
    private double springConstant;
    private double massFriction;
    private double jitter;

    //----------------------------------------------
    // Constructors
    //----------------------------------------------

    /**
     * The Spring constructor that acts as a generator of a
     * linear spring-mass network.
     *
     * @param Instrument The instrument class of which this is a part - usually 'this'
     * @param nodes      The number of spring-mass pairs in the network.
     */
    public Spring(Instrument inst, int nodes) {
        this(inst, nodes, 44100, 1);
    }

    /**
     * The Spring constructor that acts as a generator of a
     * linear spring-mass network.
     *
     * @param Instrument     The instrument class of which this is a part - usually 'this'
     * @param nodes          The number of spring-mass pairs in the network.
     * @param springConstant The stiffness of the spring.
     * @param massFriction   The weight, inertia, of the virtual mass.
     */
    public Spring(Instrument inst, int nodes, double springConstant, double massFriction) {
        this(inst, nodes, springConstant, massFriction, 0.0, 44100, 1);
    }

    /**
     * The Spring constructor that acts as a generator of a
     * linear spring-mass network.
     *
     * @param Instrument     The instrument class of which this is a part - usually 'this'
     * @param nodes          The number of spring-mass pairs in the network.
     * @param springConstant The stiffness of the spring.
     * @param massFriction   The weight, inertia, of the virtual mass.
     * @param jitter         The amount of randomness (non linearity) in the network.
     * @param sampleRate     The number of spring recalulations per second of sound.
     * @param channels       The nuber of channels, 1 = mono, 2 = stereo, etc.
     */
    public Spring(Instrument inst, int nodes, double springConstant,
                  double massFriction, double jitter, int sampleRate, int channels) {
        super(inst, sampleRate, "[WaveTable]");
        this.numberOfNodes = nodes;
        this.springConstant = springConstant;
        this.jitter = jitter;
        this.massFriction = massFriction;
        this.channels = channels;
    }

    //----------------------------------------------
    // Methods
    //----------------------------------------------
    public void build() {
        springNetwork = new SpringPipe(numberOfNodes, springConstant, massFriction, jitter);
    }

    /**
     * Returns a sample value to each channel generated by the spring model.
     *
     * @param buffer The sample buffer.
     */
    public int work(float[] buffer) throws AOException {
        int ret = 0; //the number of samples to return
        // run the appropiate code for the chosen noise type
        for (; ret < buffer.length; ) {
            for (int j = 0; j < channels; j++) {
                // change to an int ( before csting as float) for soem cool gaininess.
                buffer[ret++] = (float) (springNetwork.getNextNodePosition(0) / (40 / numberOfNodes) - 3.0);
            }
        }
        return ret;
    }
}
